import { chain, Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';

const devDependencies = [
    {
        name: '@wangdevops/ngxs-schematics',
        version: '*',
    },
];

export function ngAdd(_options: any): Rule {
    return (_tree: Tree, _context: SchematicContext) => {
        return chain([
            addDevDependencies(),
            addPackageInstallTask(),
        ])(_tree, _context);
    };
}

function addPackageInstallTask() {
    return (_tree: Tree, _context: SchematicContext) => {
        const depNames = devDependencies.map(d => d.name).join(' ');
        _context.addTask(
            new NodePackageInstallTask({
                packageName: depNames,
            }),
        );
        return _tree;
    };
}

function addDevDependencies() {
    return (_tree: Tree, _context: SchematicContext) => {
        devDependencies.forEach(d => {
            addDependencyToPackageJson(
                _tree,
                'devDependencies',
                d.name,
                d.version,
            );
        });
        return _tree;
    };
}

export type DependencyTypes =
    | 'dependencies'
    | 'devDependencies'
    | 'optionalDependencies'
    | 'peerDependencies';

/**
 * Adds a package to the package.json
 */
export function addDependencyToPackageJson(
    tree: Tree,
    type: DependencyTypes,
    pkg: string,
    version: string = 'latest',
): Tree {
    if (tree.exists('/package.json')) {
        const sourceText = tree.read('/package.json')!.toString('utf-8');
        const json = JSON.parse(sourceText);
        if (!json[type]) {
            json[type] = {};
        }

        if (!json[type][pkg]) {
            json[type][pkg] = version;
        }

        tree.overwrite('/package.json', JSON.stringify(json, null, 2));
    }

    return tree;
}
